// 导入工具包
import tools from '@/tools'

/**
 * @functionName idCardLength
 * @param {String} idcard 验证的身份证
 * @param {Number} length 验证的身份证长度
 * @return {Object} 返回结果
 * @description 验证的身份证长度
 * @author 张航
 * @date 2020-04-15 16:30:37
 * @version V1.0.0
 */
export const idCardLength = (idcard = '', length = 18) => {
  // 获取字符串长度
  const l = idcard.length

  // 初始化返回参数
  const resultObj = tools.resultObj(
    { idcard, length },
    false,
    `验证不通过，长度为${l}位`
  )

  // 获取数据类型
  const datatype = tools.getRawType(idcard)
  if (datatype !== 'String') {
    resultObj.message = `参数"${idcard}"类型不正确,请传入[String]类型！`
    return resultObj
  }

  if (l === length) {
    resultObj.result = true
    resultObj.message = `验证通过，长度为${l}位`
    return resultObj
  }

  return resultObj
}

/**
 * @functionName idCardSimple
 * @param {String} idcard 验证的身份证
 * @param {Number} length 验证的身份证长度
 * @return {Object} 返回结果
 * @description 身份证简单验证，验证地区、出生日期、性别
 * @author 张航
 * @date 2020-04-15 17:47:00
 * @version V1.0.0
 */
export const idCardSimple = (idcard = '', length = 18) => {
  // 验证长度
  const lengthRes = idCardLength(idcard, length)
  if (!lengthRes.result) {
    return lengthRes
  }

  // 初始化返回参数
  const resultObj = { ...lengthRes }

  // 初始化额外信息
  resultObj.other = {}

  // 获取地区
  const area = idcard.substring(0, 2)

  // 存储地区信息
  resultObj.other.areaCode = idcard.substring(0, 6)

  // 检测地区
  const areaRes = checkArea(area)
  resultObj.other.areaName = areaRes.area
  if (!areaRes.result) {
    resultObj.result = false
    resultObj.message = `该身份证地区[${area}]有误。`
    return resultObj
  }
  // 获取生日
  const birthday = length === 15
    // 15位出生日期是7-12位
    ? `19${idcard.substring(6, 12)}`
    // 18位出生日期是7-14位
    : idcard.substring(6, 14)

  // 存储出生日期
  resultObj.other.birthday = `${birthday.substring(0, 4)}-${birthday.substring(4, 6)}-${birthday.substring(6, 8)}`

  // 检测生日
  const birthdayRes = checkBirthday(birthday)
  resultObj.other.age = birthdayRes.age
  if (!birthdayRes.result) {
    resultObj.result = false
    resultObj.message = `该身份证出生日期[${birthday}]有误。`
    return resultObj
  }

  // 获取性别
  const genderCode = length === 15
    // 15位性别是15位
    ? idcard.substring(14, 15)
    // 18位性别是17位
    : idcard.substring(16, 17)

  const gender = parseInt(genderCode) % 2 === 1
  resultObj.other.gender = gender ? '男' : '女'

  // const rule = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
  // if (!rule.test(idcard)) {
  //   resultObj.result = false
  //   resultObj.message = `该身份证[${idcard}]不符合要求。`
  //   return resultObj
  // }

  return resultObj
}

/**
 * @functionName idCardStrict
 * @param {String} idcard 验证的身份证
 * @return {Object} 返回结果
 * @description 身份证严格校验
 * @author 张航
 * @date 2020-04-15 18:15:54
 * @version V1.0.0
 */
export const idCardStrict = (idcard = '') => {
  // 简单验证
  const simpleRes = idCardSimple(idcard)
  if (!simpleRes.result) {
    return simpleRes
  }

  // 初始化返回参数
  const resultObj = { ...simpleRes }

  // 获取校验码
  const code = idcard.substring(17)
  // 检测校验码
  const codeRes = checkCode(idcard)
  if (!codeRes) {
    resultObj.result = false
    resultObj.message = `该身份证校验位[${code}]有误。`
    return resultObj
  }

  return resultObj
}

/**
 * @functionName checkArea
 * @param {String} val 检测的字符串
 * @return {Object} 返回结果
 * @description 检测地区
 * @author 张航
 * @date 2020-04-15 17:29:19
 * @version V1.0.0
 */
const checkArea = (val = '') => {
  const pattern = /^[1-9][0-9]/
  const provs = {
    11: '北京',
    12: '天津',
    13: '河北',
    14: '山西',
    15: '内蒙古',
    21: '辽宁',
    22: '吉林',
    23: '黑龙江',
    31: '上海',
    32: '江苏',
    33: '浙江',
    34: '安徽',
    35: '福建',
    36: '江西',
    37: '山东',
    41: '河南',
    42: '湖北',
    43: '湖南',
    44: '广东',
    45: '广西',
    46: '海南',
    50: '重庆',
    51: '四川',
    52: '贵州',
    53: '云南',
    54: '西藏',
    61: '陕西',
    62: '甘肃',
    63: '青海',
    64: '宁夏',
    65: '新疆',
    71: '台湾',
    81: '香港',
    82: '澳门'
  }
  if (pattern.test(val)) {
    if (provs[val]) {
      return { result: true, area: provs[val] }
    }
  }
  return { result: false, area: '地区编码不符。' }
}

/**
 * @functionName checkBirthday
 * @param {String} val 检测的字符串
 * @return {Boolean} 返回结果
 * @description 检测出生日期
 * @author 张航
 * @date 2020-04-15 17:05:30
 * @version V1.0.0
 */
const checkBirthday = (val = '') => {
  const rule = /^(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)$/
  if (rule.test(val)) {
    const year = val.substring(0, 4)
    const month = val.substring(4, 6)
    const day = val.substring(6, 8)
    const age = calcAge(val)
    const date = new Date(`${year}-${month}-${day}`)
    // 出生日期是否大于当前时间
    if (date > new Date()) {
      return { result: false, age: '出生日期不能大于当前时间。' }
    }
    // 月份是否相等
    if (date && date.getMonth() === (parseInt(month) - 1)) {
      return { result: true, age }
    }
  }
  return { result: false, age: '出生日期有误。' }
}

/**
 * @functionName calcAge
 * @param {String} 参数
 * @return {Object} 返回结果
 * @description 计算年龄
 * @author 张航
 * @date 2020-04-20 09:49:33
 * @version V1.0.0
 */
const calcAge = (val = '') => {
  // 获取当前时间
  const nowYear = parseInt(new Date().getFullYear())
  const now = tools.getTimeStamp()

  // 获取出生日期
  const year = parseInt(val.substring(0, 4))
  const month = parseInt(val.substring(4, 6))
  const day = parseInt(val.substring(6, 8))
  const date = tools.getTimeStamp(new Date(`${year}-${month}-${day}`))

  // 获取总天数
  let total = Math.floor((now - date) / (1000 * 60 * 60 * 24))

  // 获取闰年天数
  let leapNum = 0
  for (let i = 0; i < (nowYear - year + 1); i++) {
    if (tools.isLeapYear(year + i)) {
      leapNum = leapNum + 1
    }
  }
  // 处理闰年
  total = total - leapNum

  // 计算年
  const ageYear = Math.floor(total / 365)

  if (ageYear < 1) {
    return 0
  }

  return ageYear
}

/**
 * @functionName checkCode
 * @param @param {String} val 检测的字符串
 * @return {Boolean} 返回结果
 * @description 检测校验位
 * @author 张航
 * @date 2020-04-15 18:03:30
 * @version V1.0.0
 */
const checkCode = (val = '') => {
  const rule = /^[1-9]\d{5}(18|19|20)\d{2}((0[1-9])|(1[0-2]))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/
  const factor = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
  const parity = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
  const code = val.substring(17)
  if (rule.test(val)) {
    let sum = 0
    for (let i = 0; i < 17; i++) {
      sum += val[i] * factor[i]
    }
    if (parity[sum % 11] === code.toUpperCase()) {
      return true
    }
  }
  return false
}
